package pl.edu.mimuw.irs.rcp.controller.editor.util;

import java.util.Collection;
import java.util.LinkedHashSet;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

import pl.edu.mimuw.irs.core.model.design.processing.Role;
import pl.edu.mimuw.irs.core.model.design.processing.RoleInstance;
import pl.edu.mimuw.irs.rcp.util.dnd.RolesTransfer;

public class RolesTableWrapper {

	// *** Attributes

	private Collection<RoleInstance> rolesInstances;
	private Table table;
	public Collection<RoleInstance> getRolesInstances() {
		if (rolesInstances == null) rolesInstances = new LinkedHashSet<RoleInstance>();
		return rolesInstances;
	}
	
	// *** Constructors

	public RolesTableWrapper(Composite parent, int style, 
			Collection<RoleInstance> rolesInstances) {
		table = new Table(parent, style);
		this.rolesInstances = rolesInstances;
		
		redrawTable();
		
		// Drag'N'Drop
		addDragSource();
		addDropTarget();
	}
	
	// *** Methods
	
	private void redrawTable() {
		table.removeAll();
		for (RoleInstance roleInstance : getRolesInstances()) {
			TableItem item = new TableItem(table, SWT.BORDER);
			item.setText(new String[] {roleInstance.getRole().getName()});
			item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(
				ISharedImages.IMG_OBJ_ELEMENT));
			// Store resource in table item
			item.setData(roleInstance);
		}
		
		table.redraw();
	}
	
	private void addDragSource() {
		int operations = DND.DROP_MOVE | DND.DROP_COPY;
		DragSource source = new DragSource(table, operations);
		
		Transfer[] types = new Transfer[] { RolesTransfer.getInstance() };
	 	source.setTransfer(types);
		
	 	source.addDragListener(new DragSourceListener() {
	 		public void dragStart(DragSourceEvent event) {
	 			// Only start the drag if there is actually text in the
	 			// label - this text will be what is dropped on the target.
	 			if (table.getSelection().length == 0) {
	 				event.doit = false;
	 			}
	 		}
	 		public void dragSetData(DragSourceEvent event) {
	 			// Provide the data of the requested type.
	 			if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
	 				Object[] selection = table.getSelection();
	 				TableItem item = (TableItem)selection[0];
	 				RoleInstance role = (RoleInstance)item.getData();
	 				event.data = role.getRole().getName();
	 			}
	 		}
	 		public void dragFinished(DragSourceEvent event) {
		 	    // If a move operation has been performed, remove the data
		 	    // from the source
	 			
			    /*if (event.detail == DND.DROP_MOVE) {
			    	RoleInstance roleToDelete = null;
			    	int controlToDelete = -1;
			    	for (RoleInstance role : getRequirements().getRolesInstances()) {
			    		if (role.getRole().getId().equals((String)event.data))
			    			roleToDelete = role;
			    	}
			    	for (int i = 0; i < tblRoles.getItemCount(); i++) {
			    		if (tblRoles.getItem(i).getData().equals(roleToDelete)) 
			    			controlToDelete = i;
			    	}
			    	if (roleToDelete != null) getRequirement().getRolesInstances().remove(roleToDelete);
			    	if (controlToDelete >= 0) tblRoles.remove(controlToDelete);
			    }*/
	 			// TODO : DND dla usuwania 
			}
		});
	}
	
	private void addDropTarget() {
		DropTarget target = new DropTarget(table, DND.DROP_LINK | DND.DROP_DEFAULT);
		Transfer[] types = new Transfer[] { RolesTransfer.getInstance() };
		target.setTransfer(types);
		target.addDropListener(new DropTargetAdapter() {
			public void dragEnter(DropTargetEvent event) {
				if (event.detail == DND.DROP_DEFAULT) {
					//event.detail = (event.operations & DND.DROP_COPY) != 0 ? DND.DROP_COPY
					//		: DND.DROP_NONE;
					event.detail = (event.operations & DND.DROP_LINK) != 0 ? DND.DROP_LINK
							: DND.DROP_NONE;
				}
				for (int i = 0, n = event.dataTypes.length; i < n; i++) {
					if (RolesTransfer.getInstance().isSupportedType(
							event.dataTypes[i])) {
						event.currentDataType = event.dataTypes[i];
					}
				}
			}

			public void dragOver(DropTargetEvent event) {
				event.feedback = DND.FEEDBACK_SCROLL;
			}

			public void drop(DropTargetEvent event) {
				if (RolesTransfer.getInstance().isSupportedType(
						event.currentDataType)) {
					//DropTarget target = (DropTarget) event.widget;
					//Table table = (Table) target.getControl();
					Object[] roles = (Object[]) event.data;
					if (roles == null) return;
					
					for (int i = 0; i < roles.length; i++) {
						rolesInstances.add(new RoleInstance((Role) roles[i]));
					}
					
					redrawTable();
				}
				// TODO : DND dla requirements
			}
		});
	}

	public void setLayoutData(Object layoutData) {
		table.setLayoutData(layoutData);
	}

}
